import StringUtiles from "../util/StringUtiles.mjs";
import ThreadUtils from "../util/ThreadUtils.mjs";

export default class BaseLock {
    /**
     * 默认过期时间，单位毫秒
     */
    static DEFAULT_MILLISENCOND = 200;

    /**
     * 活跃重入锁
     */
    static holdLocks = new Set();

    /**
     * 锁名
     */
    key;

    /**
     * 锁值
     */
    value;

    /**
     * 过期时间，单位s
     */
    ttl;

    /**
     * 是否支持锁重入
     */
    reentrant;

    /**
     * 是否已经持有锁
     */
    hold = false;

    constructor(key, value, ttl, reentrant) {

        this.key = key;
        this.value = value;
        this.ttl = ttl;
        this.reentrant = reentrant;
    }

    /**
     * 获取锁
     * @param ttl 失效时间 毫秒
     * @param interval 重试间隔 毫秒
     * @param maxRetry 重试次数
     * @returns {Promise<boolean|*|boolean>}
     */
    async acquire(ttl, interval=0, maxRetry=0) {

        if (this.getClient() === null || StringUtiles.isEmpty(this.key)) {  // 空锁
            return false;
        } else if (this.reentrant && BaseLock.holdLocks.has(this.key)) {  // 可重入锁
            return true;
        }

        this.ttl = (ttl ? ttl : BaseLock.DEFAULT_MILLISENCOND);

        try {
            if (!await this.lock() && maxRetry > 0) {
                ThreadUtils.sleep(interval);
                return this.acquire(ttl, interval, maxRetry - 1);
            }
        } catch (e) {
            if (maxRetry > 0) {
                try {
                    ThreadUtils.sleep(interval);
                    return this.acquire(ttl, interval, maxRetry - 1);
                } catch (e1) {
                    throw e1;
                }
            }
        }

        return this.hold;
    }

    getClient() {}

    /**
     *  抢锁
     */
    lock(){}

    /**
     * 释放锁
     */
    release(){}
}
